package com.talios.jira.browser;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ListTableModel;
import com.talios.jira.feeds.FeedBuilder;
import com.talios.jira.feeds.FeedException;
import com.talios.jira.feeds.filters.FeedFilter;

import java.awt.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

/**
 * Created by IntelliJ IDEA. User: amrk Date: 21/01/2004 Time: 22:13:53 To change this template use File | Settings |
 * File Templates.
 */
public class JiraIssuesTableModel extends ListTableModel {
    private static final Logger LOGGER = Logger.getInstance(JiraIssuesTableModel.class.toString());

    private List<JiraItem> tableData;
    private List<JiraItem> filteredTableData;

    private FeedBuilder feedBuilder;
    private IssueBrowserPanel issueBrowserPanel;
    private Project project;
    private ColumnSetting[] columnSettings;

    /**
     * @jira INTPLUG-17 Now updating feed in a new thread.
     */
    public void refreshModel(final Runnable runAfter) {
        ProgressManager.getInstance().run(new Task.Backgroundable(project, "Refreshing Issues", true) {
            public void run(ProgressIndicator indicator) {
                try {
                    if (project != null) {
                        issueBrowserPanel.getMainPanel().setCursor(new Cursor(Cursor.WAIT_CURSOR));

                        tableData = new ArrayList(feedBuilder.buildFeedData());
                        filteredTableData = tableData;
                        setItems(filteredTableData);

                        issueBrowserPanel.getMainPanel().setCursor(new Cursor(Cursor.DEFAULT_CURSOR));

                        runAfter.run();
                    }
                } catch (FeedException e) {
                    LOGGER.debug("Problem reading feed: " + e.getMessage());
                }
            }
        });
    }

    public void filterIssuesWith(FeedFilter feedFilter) {
        filteredTableData = feedFilter.filter(tableData);
        if (filteredTableData != null && !filteredTableData.isEmpty()) {
            setItems(filteredTableData);
        } else {
            setItems(new ArrayList());
        }

    }

    /**
     * @param issueBrowserPanel
     * @param feedBuilder
     */
    public JiraIssuesTableModel(Project project, IssueBrowserPanel issueBrowserPanel, FeedBuilder feedBuilder, ColumnSetting[] columnSettings) {

        super(getConfiguredColumnInfo(columnSettings));

        this.columnSettings = columnSettings;
        this.issueBrowserPanel = issueBrowserPanel;
        this.feedBuilder = feedBuilder;
        this.project = project;
    }

    private static ColumnInfo[] getConfiguredColumnInfo(ColumnSetting[] columnSettings) {
        Map columnMap = ColumnMetaInfo.getColumnDefinitions();
        List columnList = new ArrayList();

        for (ColumnSetting columnSetting : columnSettings) {
            ColumnMetaInfo columnMetaInfo = (ColumnMetaInfo) columnMap.get(columnSetting.getId());
            if (columnMetaInfo != null) {
                columnMetaInfo.setPosition(columnSetting.getPosition());
                ReflectiveColumnInfo columnInfo = new ReflectiveColumnInfo(columnMetaInfo.getId(), columnMetaInfo);
                columnList.add(columnInfo);
            } else {
                LOGGER.error("Unable to find column named " + columnSetting.getId());
            }
        }

        // Sort the columns
        Collections.sort(columnList, new Comparator() {
            public int compare(Object o1, Object o2) {
                ReflectiveColumnInfo r1 = (ReflectiveColumnInfo) o1;
                ReflectiveColumnInfo r2 = (ReflectiveColumnInfo) o2;
                return new Integer(r1.getColumnMetaInfo().getPosition()).compareTo(
                        r2.getColumnMetaInfo().getPosition());

            }
        });


        ColumnInfo[] columnInfos = (ColumnInfo[]) columnList.toArray(new ColumnInfo[]{});
        return columnInfos;
    }

    public int getRowCount() {
        return filteredTableData == null ? 0 : filteredTableData.size();
    }

    public JiraItem getItemAt(int rowIndex) {
        JiraItem item = filteredTableData.get(rowIndex);
        return item;
    }

    public Object getValueAt(int rowIndex, int columnIndex) {

        ReflectiveColumnInfo columnInfo = (ReflectiveColumnInfo) getColumnInfos()[columnIndex];
        ColumnMetaInfo columnMetaInfo = columnInfo.getColumnMetaInfo();
        JiraItem item = filteredTableData.get(rowIndex);

        Object value = null;

        try {
            String getter = ReflectiveTools.buildGetter(columnMetaInfo.getDisplayFieldName());
            Method method = JiraItem.class.getMethod(getter);
            value = method.invoke(item);
        } catch (IllegalAccessException e) {
            LOGGER.error("Unable to access getter for " + columnMetaInfo.getDisplayFieldName(), e);
        } catch (NoSuchMethodException e) {
            LOGGER.error("Unable to access getter for " + columnMetaInfo.getDisplayFieldName(), e);
        } catch (InvocationTargetException e) {
            LOGGER.error("Unable to access getter for " + columnMetaInfo.getDisplayFieldName(), e);
        }

        if (value != null) {
            // Load format from settings
            SimpleDateFormat format = new SimpleDateFormat("dd/MMM/yyyy");

            if (value instanceof Date) {
                return format.format(value);
            } else {
                return value.toString();
            }

        } else {
            return "";
        }
    }

    public List<JiraItem> getTableData() {
        return tableData;
    }

    public List<JiraItem> getFilteredTableData() {
        return filteredTableData;
    }

}
